using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Library.WebControls.Ds;
using Library.WebControls.SimplePaging;
using System.ComponentModel;
using System.Drawing;


namespace Library.WebControls.SimpleDataView {
	[ToolboxBitmap(typeof(SpDataView), "Library.WebControls.SimpleDataView.SpDataView.bmp")]
	[Designer(typeof(SpDataViewDesign))]
	[SupportsEventValidation]
	[DefaultProperty("ItemTemplate")]
	[ToolboxData("<{0}:SPDataView runat=server></{0}:SPDataView>")]
	[DesignTimeVisible(true)]
	public class SpDataView : BaseAjaxControl, IPagingControl {

		protected override string StyleSheetFileName {
			get { return "spdataview-ui.css"; }
		}
		protected const string SpDataViewControlCallbackParameter = "__SPDATAVIEWRQP_";
		protected const string SpDataViewControlCallbackData = "__SPDATAVIEWRQD_";
		protected const string SpDataViewControlCallbackPageIndex = "__SPDATAVIEWPID_";
		protected const string SpDataViewControlCallbackPageSize = "__SPDATAVIEWPS_";
		protected const string SpDataViewControlCallbackFunction = "__SPDATAVIEWRQF_";
		protected const string SpDataViewControlCallbackServerId = "__SPDATAVIEWRQSID_";
		public static bool IsDataViewCallback(Page page) {
			return page.Request[SpDataViewControlCallbackParameter] == "T";
		}

		protected internal RequestType RequestType { get; set; }
		private int _repeatColumn = 3;
		//private int _pageIndex = 1;
		//private int _pageSize = 10;
		//private int _totalItem;
		private bool _isCallback;

		private HtmlGenericControl _divContainer;
		private HtmlGenericControl _divDataview;
		private HtmlGenericControl _divContent;
		

		//private Table _dvTable;
		private SpPaging _pagingControl;
		[Description("Provides access to an SimpleGridView's edit template form.")]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[MergableProperty(false)]
		[Category("Data")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[DefaultValue("")]
		public ClientScript ClientScript { private set; get; }


		[DefaultValue("")]
		[PersistenceMode((PersistenceMode.InnerProperty))]
		[Browsable(false)]
		[TemplateContainer(typeof(SpDataViewItemTemplate))]
		public ITemplate ItemTemplate { get; set; }

		public RepeatDirection Direction { get; set; }

		public SPRenderMode RenderMode { get; set; }

		public int RepeatColumn {
			get { return _repeatColumn; }
			set {
				if (value <= 0) {
					throw new ArgumentException("RepeatColumn: value smaller zero!");
				}
				_repeatColumn = value;
			}
		}

		[Browsable(false)]
		public object DataSource { get; set; }

		public int PageIndex {
			get {
				EnsureChildControls();
				return PagingControl.PageIndex;
			}
			set {
				if (value > 0) {
					EnsureChildControls();
					PagingControl.PageIndex = value;
				}
			}
		}

		public int PageSize {
			get {
				EnsureChildControls();
				return PagingControl.PageSize;
			}
			set {
				if (value > 0) {
					EnsureChildControls();
					PagingControl.PageSize = value;
				}

			}
		}

		public int TotalItems {
			get {
				EnsureChildControls();

				return PagingControl.TotalItems;
			}
			set {
				if (value >= 0)
					PagingControl.TotalItems = value;
			}
		}

		public PagingType PagingType { get; set; }

		[Browsable(false)]
		public override bool IsCallback {
			get {
				return _isCallback;
			}
		}


		[Description("")]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[MergableProperty(false)]
		[Category("Data")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[DefaultValue("")]
		public SpPaging PagingControl {
			get {
				EnsureChildControls();
				return _pagingControl;
			}
		}


		public VerticalAlign ItemVertical { get; set; }

		public HorizontalAlign ItemHorizontal { get; set; }


		protected override void CreateChildControls() {
		
		
			_divContainer = new HtmlGenericNaming("div");
			Controls.Add(_divContainer);
			
			_divDataview = new HtmlGenericControl("div");
			_divDataview.Attributes["class"] = "spdataview";
			_divContainer.Controls.Add(_divDataview);
			_divContent = new HtmlGenericControl("div");
			_divContent.Attributes["class"] = "spdv-content";
			_divDataview.Controls.Add(_divContent);
			var divPaging = new HtmlGenericControl("div");
			divPaging.Attributes["class"] = "spdv-paging";
			_divDataview.Controls.Add(divPaging);

			var divPagingContent = new HtmlGenericControl("div");
			divPagingContent.Attributes["class"] = "spdv-paging-content";
			divPaging.Controls.Add(divPagingContent);
			_pagingControl = new SpPaging();

			divPagingContent.Controls.Add(_pagingControl);

		}

		public override string ID {
			get {
				EnsureChildControls();
				return _divContainer.ID;
			}
			set {
				EnsureChildControls();
				_divContainer.ID = value;

			}
		}

		public override string ClientID {
			get { return _divContainer.ClientID; }
		}

		public Unit Width {
			get {
				EnsureChildControls();
				return new Unit(_divContainer.Style[HtmlTextWriterStyle.Width]);
			}
			set {
				EnsureChildControls();
				_divContainer.Style[HtmlTextWriterStyle.Width] = value.ToString();

			}
		}





		private bool _isDataBinding;

		public SpDataView() {
			PagingType = PagingType.Manual;
			RenderMode = SPRenderMode.Table;
			ClientScript = new ClientScript();
		}

		private void DvDataBinding(bool isRaiseBindingEvent) {
			if (isRaiseBindingEvent)
				OnDataBinding(EventArgs.Empty);
			_divContent.Controls.Clear();

			if (DataSource != null) {
				var dsWrapper = new DataSourceWrapper(DataSource);

				if (PagingType == PagingType.Automatic) {
					while (dsWrapper.MoveNext()) { }

					TotalItems = dsWrapper.Index + 1;
					dsWrapper.Reset();
					int totalPage = TotalItems / PageSize;
					if (totalPage * PageSize < TotalItems) {
						totalPage++;
					}
					if (PageIndex > totalPage) {
						PageIndex = totalPage;
					}
					int from = (PageIndex - 1) * PageSize;
					if (from >= 0) {
						int to = PageIndex * PageSize;
						if (to > TotalItems) {
							to = TotalItems;
						}
						dsWrapper = dsWrapper.Paging(from, to);
					}
				} else {
					int totalPage = TotalItems / PageSize;
					if (totalPage * PageSize < TotalItems) {
						totalPage++;
					}
					if (PageIndex > totalPage) {
						PageIndex = totalPage;
					}
				}
				if (RenderMode == SPRenderMode.Table) {
					RenderTableMode(dsWrapper, _divContent);
				} else if (RenderMode == SPRenderMode.Flat) {
					RenderFlatMode(dsWrapper, _divContent);
				}
			}

			base.DataBind();
			_isDataBinding = true;
		}
		public override void DataBind() {
			DvDataBinding(true);
		}

		private void RenderTableMode(DataSourceWrapper dsWrapper, Control owner) {
			var tdContain = new Table { Width = new Unit("100%") };
			owner.Controls.Add(tdContain);
			TableRow row = null;
			int running = 0;
			while (dsWrapper.MoveNext()) {
				running++;
				if (running == 1) {
					row = new TableRow();
					tdContain.Rows.Add(row);
				}
				var cell = new TableCell();
				row.Cells.Add(cell);
				cell.CssClass = "spdvitem";
				cell.HorizontalAlign = ItemHorizontal;
				cell.VerticalAlign = ItemVertical;
				var item = new SpDataViewItemTemplate(dsWrapper.Current.OriginalItem, dsWrapper.Index);
				cell.Controls.Add(item);
				ITemplate template = ItemTemplate;
				if (template != null) {
					template.InstantiateIn(item);
				}

				OnItemBound(new SimpleItemBoundEventArgs<SpDataViewItemTemplate>(dsWrapper.Current, item));

				if (running == RepeatColumn) {
					running = 0;
				}
			}
		}

		private void RenderFlatMode(DataSourceWrapper dsWrapper, Control owner) {
			var holder = new PlaceHolder();
			owner.Controls.Add(holder);
			while (dsWrapper.MoveNext()) {
				var item = new SpDataViewItemTemplate(dsWrapper.Current.OriginalItem, dsWrapper.Index);

				holder.Controls.Add(item);
				ITemplate template = ItemTemplate;
				if (template != null) {
					template.InstantiateIn(item);
				}
				OnItemBound(new SimpleItemBoundEventArgs<SpDataViewItemTemplate>(dsWrapper.Current, item));
			}
		}

		protected override void OnInit(EventArgs e) {
			base.OnInit(e);
			if (Request != null) {
				_isCallback = IsDataViewCallback(Page) && _divContainer.ClientID == Request[SpDataViewControlCallbackServerId];
				if (_isCallback) {
					var requestFunction = Request[SpDataViewControlCallbackFunction].ParseInt();
					if (requestFunction.HasValue) {
						RequestType = (RequestType)requestFunction.Value;
					}
					if (RequestType != RequestType.None) {
						var pageIndex = Request[SpDataViewControlCallbackPageIndex].ParseInt();
						var pageSize = Request[SpDataViewControlCallbackPageSize].ParseInt();
						if (pageIndex.HasValue) PageIndex = pageIndex.Value;
						if (pageSize.HasValue) PageSize = pageSize.Value;
					}
				}
			} else {
				_isCallback = false;
			}
		}

		protected override void OnLoad(EventArgs e) {
			base.OnLoad(e);
			IncludeScriptOnLoad(typeof(SpDataView), "DataView", "Library.WebControls.SimpleDataView.include.SpDataView.js", UtilLib);
			if (IsCallback) {
				switch (RequestType) {
					case RequestType.CustomCallback: // user send custom callback												
						OnCustomCallback(new CustomCallbackEventArgs(Request[SpDataViewControlCallbackData]));
						break;
					case RequestType.DataCallback: // user send custom data callback						
						OnDataCallback(new CustomCallbackEventArgs(Request[SpDataViewControlCallbackData]));
						break;
					case RequestType.PageIndexChange: // Page index change
						OnPageIndexChange(EventArgs.Empty);
						break;
				}
			}
		}

		protected virtual void OnPageIndexChange(EventArgs e) {
			EventHandler handler = PageIndexChanged;
			if (handler != null) {
				try {
					handler(this, e);
				} catch (Exception ex) {
					WriteError(ex);
				}
			}
		}

		protected virtual void OnCustomCallback(CustomCallbackEventArgs e) {
			CustomCallbackEventHandler handler = CustomCallback;
			if (handler != null) {
				try {
					handler(this, e);
					ProcessCustomCallbackEventArgs(e);
				} catch (Exception ex) {
					WriteError(ex);
				}
			}
		}

		protected virtual void OnDataCallback(CustomCallbackEventArgs e) {
			CustomCallbackEventHandler handler = DataCallback;
			if (handler != null) {
				try {
					handler(this, e);
					ProcessCustomCallbackEventArgs(e);
				} catch (Exception ex) {
					WriteError(ex);
				}
			}
		}

		public override bool ClientVisible {
			get {
				EnsureChildControls();
				return _divContainer.Style[HtmlTextWriterStyle.Display] != "none";
			}
			set {
				EnsureChildControls();
				if (value) {
					_divContainer.Style[HtmlTextWriterStyle.Display] = "";
				} else {
					_divContainer.Style[HtmlTextWriterStyle.Display] = "none";
				}
			}
		}

		public override bool ClientEnable {
			get {
				EnsureChildControls();
				return base.ClientEnable;
			}
			set {
				base.ClientEnable = value;
				EnsureChildControls();
				if (value)
					_divContainer.Attributes.Remove("disabled");
				else {
					_divContainer.Attributes["disabled"] = "disabled";
				}
			}
		}

		protected override void CreateClientObjectAtRender(HtmlTextWriter writer) {
			BeginScriptTag(writer);
			writer.Write(String.Format("var {0}=new SpDataView('{0}','{1}','{2}','{3}', {4});", ClientName, _divContainer.ClientID, PagingControl.CurrentPageContainer.ClientID, PagingControl.RowPerPageContainer.ClientID, ClientEnable.ToString().ToLower()));
			AddScriptHandler(writer, 1, ClientScript.BeforeCallback, "AddHandler");

			EndScriptTag(writer);
		}

		protected override void Render(HtmlTextWriter writer) {
			if (Visible) {
				if (!_isDataBinding)
					DvDataBinding(false);
				_divContainer.Attributes["onkeypress"] = String.Format("return {0}.Call(1, event)", ClientName);
				if (!ClientVisible) {
					_divContainer.Style[HtmlTextWriterStyle.Display] = "none";
				}
				PagingControl.First.Attributes["onclick"] = String.Format("{0}.GetPage(1);", ClientName);
				int currentPageIndex = PagingControl.PageIndex;
				if (currentPageIndex > 1) {
					PagingControl.Preview.Attributes["onclick"] = String.Format("{0}.GetPage({1});", ClientName, currentPageIndex - 1);
				}
				int maxPageIndex = PagingControl.TotalPages;

				if (currentPageIndex < maxPageIndex) {
					PagingControl.Next.Attributes["onclick"] = String.Format("{0}.GetPage({1});", ClientName, currentPageIndex + 1);
				}
				PagingControl.Last.Attributes["onclick"] = String.Format("{0}.GetPage({1});", ClientName, maxPageIndex);
				PagingControl.Refresh.Attributes["onclick"] = String.Format("{0}.Refresh();", ClientName);
				if (!IsCallback) {
					base.Render(writer);
				} else {
					WriteCustomCallbackCompleteResult();
					if (RequestType == RequestType.CustomCallback || RequestType == RequestType.PageIndexChange)
						_divDataview.RenderControl(writer);
					FlushAndEndCallback();
				}
			}
		}

		public event SimpleItemBoundEventHandler<SpDataViewItemTemplate> ItemBound;
		protected virtual void OnItemBound(SimpleItemBoundEventArgs<SpDataViewItemTemplate> e) {
			SimpleItemBoundEventHandler<SpDataViewItemTemplate> handler = ItemBound;
			if (handler != null)
				handler(this, e);
		}


		//public event DataViewItemBoundEventHandler DataViewItemBound;
		public event EventHandler PageIndexChanged;
		public event CustomCallbackEventHandler CustomCallback;
		public event CustomCallbackEventHandler DataCallback;
		//public event PagingRowCreatedEventHandler PagingRowCreated;


	}
}
